import type {
    AxiosInstance,
    AxiosRequestConfig,
    InternalAxiosRequestConfig,
    AxiosError,
    AxiosResponse
} from "axios";
import axios from "axios";
import event from "./eventEmitter";
import type { ResultData } from "./interface";

class Request {
    private service: AxiosInstance;

    constructor(config: AxiosRequestConfig) {
        this.service = axios.create(config);

        /** 请求拦截器 */
        this.service.interceptors.request.use(
            (config: InternalAxiosRequestConfig) => {
                // 在请求发送时处理一些内容
                // 比如在请求头中添加 token
                const token = localStorage.getItem("token");
                if (token) {
                    config.headers.Authorization = "Bearer " + token;
                }
                return config;
            },
            (error: AxiosError) => {
                return Promise.reject(error);
            }
        );
        /** 响应拦截器 */
        this.service.interceptors.response.use(
            (response: AxiosResponse) => {
                console.log(response);

                const { data } = response;

                if (data.code === RequestEnums.LOGINTIMEOUT) {
                    event.emit("API:SESSION_EXPIRED");
                    return Promise.reject(data);
                }
                if (data.code !== RequestEnums.SUCCESS) {
                    event.emit("API:INVALID");
                    return Promise.reject(data);
                }
                return data;
            },
            (error: AxiosError) => {
                event.emit("API:NETWORK_ERROR");
                return Promise.reject(error)
            }
        );
    }

    get<T>(url: string, params?: object): Promise<ResultData<T>> {
        return this.service.get(url, { params });
    }
    post<T>(url: string, params?: object): Promise<ResultData<T>> {
        return this.service.post(url, params);
    }
    put<T>(url: string, params?: object): Promise<ResultData<T>> {
        return this.service.put(url, params);
    }
    delete<T>(url: string, params?: object): Promise<ResultData<T>> {
        return this.service.delete(url, { params });
    }
}

enum RequestEnums {
    TIMEOUT = 10000, // 请求超时
    FAIL = 500, // 服务器异常
    INVALID = 400, // 参数错误
    LOGINTIMEOUT = 401, // 登录超时
    SUCCESS = 200, // 请求成功
}

const config: AxiosRequestConfig = {
    baseURL: import.meta.env.VITE_APP_API_URL as string,
    timeout: RequestEnums.TIMEOUT as number,
    withCredentials: true,
};

const request = new Request(config);

export default request;
